package com.senni.config;

import feign.*;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class FeignCommonContract extends DeclarativeContract {
    static final Pattern REQUEST_LINE_PATTERN = Pattern.compile("^([A-Z]+)[ ]*(.*)$");
    public FeignCommonContract(){
        super.registerMethodAnnotation(GetMapping.class,(ann, data)->{
            String[] value = ann.value();
            if(value.length==0){
                return ;
            }
            String url = value[0];
            Util.checkState(Util.emptyToNull(url) != null, "RequestLine annotation was empty on method %s.", new Object[]{data.configKey()});
            data.template().uri(url);
            data.template().method(Request.HttpMethod.valueOf(RequestMethod.GET.name()));
            data.template().decodeSlash(true);
            data.template().collectionFormat(CollectionFormat.EXPLODED);
        });
        super.registerMethodAnnotation(PostMapping.class,(ann, data)->{
            String[] value = ann.value();
            if(value.length==0){
                return ;
            }
            String url = value[0];
            Util.checkState(Util.emptyToNull(url) != null, "RequestLine annotation was empty on method %s.", new Object[]{data.configKey()});
            data.template().uri(url);
            data.template().method(Request.HttpMethod.valueOf(RequestMethod.POST.name()));
            data.template().decodeSlash(true);
            data.template().collectionFormat(CollectionFormat.EXPLODED);
        });
        super.registerMethodAnnotation(DeleteMapping.class,(ann, data)->{
            String[] value = ann.value();
            if(value.length==0){
                return ;
            }
            String url = value[0];
            Util.checkState(Util.emptyToNull(url) != null, "RequestLine annotation was empty on method %s.", new Object[]{data.configKey()});
            data.template().uri(url);
            data.template().method(Request.HttpMethod.valueOf(RequestMethod.DELETE.name()));
            data.template().decodeSlash(true);
            data.template().collectionFormat(CollectionFormat.EXPLODED);
        });
        super.registerMethodAnnotation(PutMapping.class,(ann, data)->{
            String[] value = ann.value();
            if(value.length==0){
                return ;
            }
            String url = value[0];
            Util.checkState(Util.emptyToNull(url) != null, "RequestLine annotation was empty on method %s.", new Object[]{data.configKey()});
            data.template().uri(url);
            data.template().method(Request.HttpMethod.valueOf(RequestMethod.PUT.name()));
            data.template().decodeSlash(true);
            data.template().collectionFormat(CollectionFormat.EXPLODED);
        });
        super.registerMethodAnnotation(RequestMapping.class,(ann, data)->{
            String[] value = ann.value();
            if(value.length==0){
                return ;
            }
            String url = value[0];
            Util.checkState(Util.emptyToNull(url) != null, "RequestLine annotation was empty on method %s.", new Object[]{data.configKey()});
            data.template().uri(url);
            data.template().method(Request.HttpMethod.valueOf(ann.method()[0].name()));
            data.template().decodeSlash(true);
            data.template().collectionFormat(CollectionFormat.EXPLODED);
        });
        super.registerParameterAnnotation(RequestBody.class,(paramAnnotation,data,paramIndex)->{
            String body = "{body}";
            String bodyValue="body";
            data.template().header("Content-Type","application/json");
            data.template().bodyTemplate(body);
            this.nameParam(data,bodyValue,paramIndex);
            data.formParams().add(bodyValue);
        });
        super.registerParameterAnnotation(Param.class, (paramAnnotation, data, paramIndex) -> {
            String name = paramAnnotation.value();
            Util.checkState(Util.emptyToNull(name) != null, "Param annotation was empty on param %s.", new Object[]{paramIndex});
            this.nameParam(data, name, paramIndex);
            Class<? extends Param.Expander> expander = paramAnnotation.expander();
            if (expander != Param.ToStringExpander.class) {
                data.indexToExpanderClass().put(paramIndex, expander);
            }

            if (!data.template().hasRequestVariable(name)) {
                data.formParams().add(name);
            }

        });

        super.registerMethodAnnotation(Headers.class, (header, data) -> {
            String[] headersOnMethod = header.value();
            Util.checkState(headersOnMethod.length > 0, "Headers annotation was empty on method %s.", new Object[]{data.configKey()});
            data.template().headers(toMap(headersOnMethod));
        });
        super.registerParameterAnnotation(QueryMap.class, (queryMap, data, paramIndex) -> {
            Util.checkState(data.queryMapIndex() == null, "QueryMap annotation was present on multiple parameters.", new Object[0]);
            data.queryMapIndex(paramIndex);
            data.queryMapEncoded(queryMap.encoded());
        });
        super.registerParameterAnnotation(HeaderMap.class, (queryMap, data, paramIndex) -> {
            Util.checkState(data.headerMapIndex() == null, "HeaderMap annotation was present on multiple parameters.", new Object[0]);
            data.headerMapIndex(paramIndex);
        });
        super.registerClassAnnotation(Headers.class, (header, data) -> {
            String[] headersOnType = header.value();
            Util.checkState(headersOnType.length > 0, "Headers annotation was empty on type %s.", new Object[]{data.configKey()});
            Map<String, Collection<String>> headers = toMap(headersOnType);
            headers.putAll(data.template().headers());
            data.template().headers((Map)null);
            data.template().headers(headers);
        });
    }
    private static Map<String, Collection<String>> toMap(String[] input) {
        Map<String, Collection<String>> result = new LinkedHashMap(input.length);
        String[] var2 = input;
        int var3 = input.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            String header = var2[var4];
            int colon = header.indexOf(58);
            String name = header.substring(0, colon);
            if (!result.containsKey(name)) {
                result.put(name, new ArrayList(1));
            }

            ((Collection)result.get(name)).add(header.substring(colon + 1).trim());
        }

        return result;
    }
}
